home *** CD-ROM | disk | FTP | other *** search
/ PC Media 4 / PC MEDIA CD04.iso / share / prog / h2p120 / h2pas.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-05-31  |  27.3 KB  |  1,004 lines

  1. {$A+,B-,F-,G+,I-,P-,Q-,R-,S-,T-,V-,X+,Y+}
  2. Program H2Pas;
  3. { Program:   H2PAS
  4.   Version:   1.10
  5.   Purpose:   convert C header files to some kind of Pascal units
  6.  
  7.   Developer: Peter Sawatzki (ps) (c) 1993
  8.              Buchenhof 3, 58091 Hagen, Germany
  9.  CompuServe: 100031,3002
  10.  
  11.   revision history:
  12.   date       version  author   modification
  13.   11/03/93   1.00     ps       written
  14.   05/10/94   1.10     ps       add EXEHDR import support
  15. }
  16. Uses
  17.   Objects,
  18.   Strings;
  19.  
  20. Const
  21.   Version = 'H2Pas v.1.20';
  22.   H2PasIni= 'H2Pas.Ini';
  23.   StdUses: pChar = 'Uses'#13#10+
  24.                    '  Os2Def;';
  25.   HasImports: Boolean = False;
  26.   WhichBlock: (Undefd, InConst, InType, InVar, InFunc) = Undefd;
  27. Var
  28.   DstName,
  29.   Imports: String[67];
  30.  
  31.   Function WordCount(aStr, Delims: pChar): Integer;
  32.   Var
  33.     Count: Integer;
  34.     EndStr: pChar;
  35.   Begin
  36.     EndStr:= StrEnd(aStr);
  37.     Count:= 0;
  38.     While aStr<=EndStr Do Begin
  39.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])<>Nil) Do Inc(aStr);
  40.       If aStr<=EndStr Then Inc(Count);
  41.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Inc(aStr)
  42.     End;
  43.     WordCount:= Count
  44.   End;
  45.  
  46.   Function WordPosition (aStr, Delims: pChar; No: Integer): pChar;
  47.   Var
  48.     Count: Integer;
  49.     EndStr: pChar;
  50.   Begin
  51.     EndStr:= StrEnd(aStr);
  52.     Count:= 0;
  53.     WordPosition:= Nil;
  54.     While (aStr<=EndStr) And (Count<>No) Do Begin
  55.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])<>Nil) Do Inc(aStr);
  56.       If aStr<=EndStr Then Inc(Count);
  57.       If Count<>No Then
  58.         While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Inc(aStr)
  59.       Else
  60.         WordPosition:= aStr
  61.     End
  62.   End;
  63.  
  64.   Function ExtractWord (aDst, aStr, Delims: pChar; No: Integer): pChar;
  65.   Var
  66.     EndStr: pChar;
  67.   Begin
  68.     ExtractWord:= aDst;
  69.     aStr:= WordPosition(aStr, Delims, No);
  70.     If Assigned(aStr) Then Begin
  71.       EndStr:= StrEnd(aStr);
  72.       While (aStr<=EndStr) And (StrScan(Delims, aStr[0])=Nil) Do Begin
  73.         aDst[0]:= aStr[0];
  74.         Inc(aStr);
  75.         Inc(aDst)
  76.       End
  77.     End;
  78.     aDst[0]:= #0
  79.   End;
  80.  
  81.   Function Trim (aDst, aSrc: pChar): pChar;
  82.   Var
  83.     EndStr: pChar;
  84.   Begin
  85.     Trim:= aDst;
  86.     If Not Assigned(aSrc) Or (aSrc[0]=#0) Then
  87.       aDst[0]:= #0
  88.     Else Begin
  89.       EndStr:= StrEnd(aSrc);
  90.       While (aSrc<=EndStr) And (aSrc[0]<=' ') Do
  91.         Inc(aSrc);
  92.       StrCopy(aDst, aSrc);
  93.       EndStr:= StrEnd(aDst);
  94.       While (EndStr>=aDst) And (EndStr[0]<=' ') Do Begin
  95.         EndStr[0]:= #0;
  96.         Dec(EndStr)
  97.       End
  98.     End
  99.   End;
  100.  
  101.   Function Pad (aDst, aSrc: pChar; Count: Integer): pChar;
  102.   Begin
  103.     Pad:= aDst;
  104.     If aDst<>aSrc Then
  105.       StrCopy(aDst, aSrc);
  106.     Count:= Count-StrLen(aDst);
  107.     aDst:= StrEnd(aDst);
  108.     While Count>0 Do Begin
  109.       aDst[0]:= ' ';
  110.       Inc(aDst);
  111.       Dec(Count)
  112.     End;
  113.     aDst[0]:= #0
  114.   End;
  115.  
  116. Function StrIPos(Str1, Str2: PChar): PChar;
  117. Var
  118.   EndStr: pChar;
  119.   Len: Integer;
  120. Begin
  121.   StrIPos:= Nil;
  122.   EndStr:= StrEnd(Str1);
  123.   Len:= StrLen(Str2);
  124.   Repeat
  125.     Str1:= StrScan(Str1, Str2[0]);
  126.     If Str1=Nil Then Exit;
  127.     If StrLIComp(Str1, Str2, Len)=0 Then Begin
  128.       StrIPos:= Str1;
  129.       Exit
  130.     End;
  131.     Inc(Str1)
  132.   Until Str1>EndStr
  133. End;
  134.  
  135.   Function JustFilename(PathName : string) : string;
  136.   {-Return just the filename of a pathname}
  137.   Var
  138.     I: Word;
  139.   Begin
  140.     I:= Succ(Word(Length(PathName)));
  141.     Repeat
  142.       Dec(I);
  143.     Until (PathName[I] in  ['\', ':', #0]) or (I = 0);
  144.     JustFilename := Copy(PathName, Succ(I), 64);
  145.   End;
  146.  
  147.   function JustName(PathName : string) : string;
  148.     {-Return just the name (no extension, no path) of a pathname}
  149.   var
  150.     DotPos : Byte;
  151.   begin
  152.     PathName := JustFileName(PathName);
  153.     DotPos := Pos('.', PathName);
  154.     if DotPos > 0 then
  155.       PathName := Copy(PathName, 1, DotPos-1);
  156.     JustName := PathName;
  157.   end;
  158.  
  159.   Function JustPath(aName: string): string;
  160.   {-Return just the path of a filename}
  161.   Var
  162.     I: Word;
  163.   Begin
  164.     I:= Succ(Word(Length(aName)));
  165.     Repeat
  166.       Dec(I);
  167.     Until (aName[I] in  ['\', ':', #0]) or (I = 0);
  168.     JustPath:= Copy(aName, 1, I)
  169.   End;
  170.  
  171.   Procedure Fatal (aMsg: pChar);
  172.   Begin
  173.     WriteLn(aMsg);
  174.     Halt(255)
  175.   End;
  176.  
  177.   Function GetLine (aDst: pChar; Var aFile: Text): pChar;
  178.   Var
  179.     aString: String;
  180.     p,i: Integer;
  181.   Begin
  182.     {$i-}
  183.     ReadLn(aFile, aString);
  184.     If IoResult<>0 Then Fatal('Read error.');
  185.     p:= Pos('//', aString);
  186.     If p>0 Then Begin
  187.       aString[p+1]:= '*';
  188.       aString:= aString+' */'
  189.     End;
  190.     p:= Pos(#9, aString);
  191.     While p>0 Do Begin
  192.       aString[p]:= ' ';
  193.       For i:= 1 To 7-((p-1) Mod 8) Do
  194.         Insert(' ', aString, p);
  195.       p:= Pos(#9, aString)
  196.     End;
  197.     GetLine:= StrPCopy(aDst, aString)
  198.   End;
  199.  
  200.   Procedure OutLn (Var aFile: Text; OutStr: pChar);
  201.   Var
  202.     oc: Char;
  203.   Begin
  204.     While OutStr[0]<>#0 Do Begin
  205.       oc:= OutStr[0];
  206.       Case oc Of
  207.         '/': If OutStr[1]='*' Then Begin
  208.                oc:= '{';
  209.                Inc(OutStr,1)
  210.              End;
  211.         '*': If OutStr[1]='/' Then Begin
  212.                oc:= '}';
  213.                Inc(OutStr)
  214.              End
  215.       End;
  216.       Write(aFile, oc);
  217.       If IoResult<>0 Then Fatal('Write error.');
  218.       Inc(OutStr)
  219.     End;
  220.     Write(aFile,#13#10);
  221.     If IoResult<>0 Then Fatal('Write error.')
  222.   End;
  223.  
  224. Procedure HeaderInfo (Var aFile: Text);
  225. Var
  226.   aLine: Array[0..100] Of Char;
  227. Begin
  228.   WriteLn(aFile, '{ Unit: ',DstName);
  229.   WriteLn(aFile, '  Version: 1.00');
  230.   WriteLn(aFile, '  translated from file ',DstName,'.H');
  231.   WriteLn(aFile, '  raw translation using '+Version+', (c) Peter Sawatzki');
  232.   WriteLn(aFile, '  fine tuned by:');
  233.   WriteLn(aFile, '    (fill in)');
  234.   WriteLn(aFile, ' ');
  235.   WriteLn(aFile, '  revision history:');
  236.   WriteLn(aFile, '  Date:    Ver: Author: Mod:');
  237.   WriteLn(aFile, '  xx/xx/94 1.00 <name>  <modification>');
  238.   WriteLn(aFile, '}');
  239.   WriteLn(aFile, 'Unit ',DstName,';');
  240.   WriteLn(aFile, 'Interface');
  241.   If StrLen(StdUses)<>0 Then
  242.     WriteLn(aFile, StdUses);
  243. End;
  244.  
  245. {-the collection part}
  246. Type
  247.   pImportEntry = ^tImportEntry;
  248.   tImportEntry = Record
  249.     TheName,
  250.     TheDLL,
  251.     TheOrd: pChar
  252.   End;
  253.   pImportCollection = ^tImportCollection;
  254.   tImportCollection = Object(tSortedCollection)
  255.     Function KeyOf(Item: Pointer): Pointer; Virtual;
  256.     Function Compare(Key1, Key2: Pointer): Integer; Virtual;
  257.     Procedure FreeItem(Item: Pointer); Virtual;
  258.   End;
  259.  
  260.   pTypeMap = ^tTypeMap;
  261.   tTypeMap = Record
  262.     F, T: pChar;
  263.   End;
  264.   pTypeMapCollection = ^tTypeMapCollection;
  265.   tTypeMapCollection = Object(tSortedCollection)
  266.     Function KeyOf(Item: Pointer): Pointer; Virtual;
  267.     Function Compare(Key1, Key2: Pointer): Integer; Virtual;
  268.     Procedure FreeItem(Item: Pointer); Virtual;
  269.   End;
  270.  
  271. Function tImportCollection.KeyOf(Item: Pointer): Pointer;
  272. Begin
  273.   KeyOf:= pImportEntry(Item)^.TheName
  274. End;
  275.  
  276. Function tImportCollection.Compare(Key1, Key2: Pointer): Integer;
  277. Begin
  278.   Compare:= StrIComp(Key1, Key2)
  279. End;
  280.  
  281. Procedure TImportCollection.FreeItem(Item: Pointer);
  282. Begin
  283.   StrDispose(pImportEntry(Item)^.TheName);
  284.   StrDispose(pImportEntry(Item)^.TheDLL);
  285.   StrDispose(pImportEntry(Item)^.TheOrd);
  286.   Dispose(pImportEntry(Item))
  287. End;
  288.  
  289. Function tTypeMapCollection.KeyOf(Item: Pointer): Pointer;
  290. Begin
  291.   KeyOf:= pTypeMap(Item)^.F
  292. End;
  293.  
  294. Function tTypeMapCollection.Compare(Key1, Key2: Pointer): Integer;
  295. Begin
  296.   Compare:= StrIComp(Key1, Key2)
  297. End;
  298.  
  299. Procedure tTypeMapCollection.FreeItem(Item: Pointer);
  300. Begin
  301.   StrDispose(pTypeMap(Item)^.F);
  302.   StrDispose(pTypeMap(Item)^.T);
  303.   Dispose(pTypeMap(Item))
  304. End;
  305.  
  306. Const
  307.   TheImports: pImportCollection = Nil;
  308.   TheFuncs: pStrCollection = Nil;
  309.   TheStructs: pStrCollection = Nil;
  310.   TheTypeMap: pTypeMapCollection = Nil;
  311.   TheModMap: pStrCollection = Nil;
  312.  
  313. Procedure CreateCollections;
  314. Begin
  315.   TheImports:= New(pImportCollection, Init(100, 50));
  316.   TheFuncs:= New(pStrCollection, Init(10, 20));
  317.   TheStructs:= New(pStrCollection, Init(10, 20));
  318.   TheTypeMap:= New(pTypeMapCollection, Init(10, 10));
  319.   TheModMap:= New(pStrCollection, Init(10, 10));
  320. End;
  321.  
  322. Procedure DestroyCollections;
  323. Begin
  324.   If Assigned(TheImports) Then Dispose(TheImports, Done);
  325.   If Assigned(TheFuncs)   Then Dispose(TheFuncs,   Done);
  326.   If Assigned(TheStructs) Then Dispose(TheStructs, Done);
  327.   If Assigned(TheTypeMap) Then Dispose(TheTypeMap, Done);
  328.   If Assigned(TheModMap)  Then Dispose(TheModMap,  Done);
  329. End;
  330.  
  331. Procedure AddImport (aName, aDLL, anOrd: pChar);
  332. Var
  333.   anEntry: pImportEntry;
  334. Begin
  335.   anEntry:= New(pImportEntry);
  336.   anEntry^.TheName:= StrNew(aName);
  337.   anEntry^.TheDLL:= StrNew(aDLL);
  338.   anEntry^.TheOrd:=  StrNew(anOrd);
  339.   TheImports^.Insert(anEntry)
  340. End;
  341.  
  342. Procedure AddFunc (aName: pChar);
  343. Begin
  344.   TheFuncs^.Insert(StrNew(aName))
  345. End;
  346.  
  347. Procedure AddStruct (aName: pChar);
  348. Begin
  349.   TheStructs^.Insert(StrNew(aName))
  350. End;
  351.  
  352. Procedure AddType (aSrc, aDst: pChar);
  353. Var
  354.   anEntry: pTypeMap;
  355. Begin
  356.   anEntry:= New(pTypeMap);
  357.   anEntry^.F:= StrNew(aSrc);
  358.   anEntry^.T:= StrNew(aDst);
  359.   TheTypeMap^.Insert(anEntry)
  360. End;
  361.  
  362. Procedure AddMod (aName: pChar);
  363. Begin
  364.   TheModMap^.Insert(StrNew(aName))
  365. End;
  366.  
  367. Function GetOrdDLL (aName, RetDLL, RetOrd: pChar): Boolean;
  368. Var
  369.   Index: Integer;
  370. Begin
  371.   If TheImports^.Search(aName, Index) Then
  372.     With pImportEntry(TheImports^.At(Index))^ Do Begin
  373.       GetOrdDLL:= True;
  374.       StrCopy(RetDLL, TheDLL);
  375.       StrCopy(RetOrd, TheOrd)
  376.     End
  377.   Else
  378.     GetOrdDLL:= False
  379. End;
  380.  
  381. Procedure ReadImports (aFileName: String);
  382. Var
  383.   aFile: Text;
  384.   aLine: Array[0..500] Of Char;
  385.   aName,
  386.   aDLL,
  387.   anOrd: Array[0..60] Of Char;
  388.   aWord: Array[0..60] Of Char;
  389. Begin
  390.   {$i-} Assign(aFile, aFileName); Reset(aFile);
  391.   If IoResult<>0 Then Exit;
  392.   HasImports:= True;
  393.   StrCopy(aDLL, '?');
  394.   While Not Eof(aFile) Do Begin
  395.     GetLine(aLine, aFile);
  396.     If StrComp(ExtractWord(aWord, aLine, ' ', 1),'Library:')=0 Then
  397.       ExtractWord(aDLL, aLine, ' ', 2)
  398.     Else
  399.     If StrComp(ExtractWord(aWord, aLine, ' ', 5),'exported,')=0 Then Begin
  400.       ExtractWord(anOrd, aLine, ' ', 1);
  401.       ExtractWord(aName, aLine, ' ', 4);
  402.       AddImport(aName, aDLL, anOrd)
  403.     End
  404.   End;
  405.   Close(aFile)
  406. End;
  407.  
  408. Procedure ReadIni;
  409. Var
  410.   IniFile: Text;
  411.   aStr: String;
  412.   aLine, Word1, Word2: Array[0..255] Of Char;
  413.   rm: (rmNone, rmTypeMap, rmModMap);
  414.   p: Integer;
  415. Begin
  416.   {$i-}
  417.   Assign(IniFile, H2PasIni); Reset(IniFile);
  418.   If IoResult<>0 Then Begin
  419.     Assign(IniFile, JustPath(ParamStr(0))+'\'+H2PasIni);
  420.     Reset(IniFile);
  421.     If IoResult<>0 Then
  422.       Exit
  423.   End;
  424.   rm:= rmNone;
  425.   While Not Eof(IniFile) Do Begin
  426.     ReadLn(IniFile, aStr);
  427.     p:= Pos(';', aStr); If (p>0) Then aStr[0]:= Chr(p-1);
  428.     StrPCopy(aLine, aStr); Trim(aLine, aLine);
  429.     If StrLen(aLine)=0 Then
  430.       Continue;
  431.     If aLine[0]='[' Then Begin
  432.       If StrIComp(aLine, '[TypeMap]')=0 Then rm:= rmTypeMap Else
  433.       If StrIComp(aLine, '[ModMap]')=0 Then rm:= rmModMap Else
  434.         rm:= rmNone;
  435.       Continue
  436.     End;
  437.     Case rm Of
  438.       rmTypeMap: AddType(Trim(Word1, ExtractWord(Word1, aLine, '=', 1)),
  439.                          Trim(Word2, ExtractWord(Word2, aLine, '=', 2)));
  440.       rmModMap:  AddMod(aLine);
  441.     End
  442.   End;
  443.   Close(IniFile)
  444. End;
  445.  
  446. Function Modifier (aPart: pChar): Boolean;
  447. Var
  448.   Index: Integer;
  449. Begin
  450.   Modifier:= TheModMap^.Search(aPart, Index)
  451. End;
  452.  
  453. Function TypeConvert (aDst, aSrc: pChar): pChar;
  454. Var
  455.   aWord: Array[0..79] Of Char;
  456.   i, anInt, anError: Integer;
  457.   aTemp: Array[0..79] Of Char;
  458.   Index: Integer;
  459. Begin
  460.   TypeConvert:= aDst;
  461.   aDst[0]:= #0;
  462.   ExtractWord(aTemp, aSrc, '[]', 2);
  463.   If StrLen(aTemp)>0 Then Begin
  464.     Val(aTemp, anInt, anError);
  465.     If anError=0 Then Begin
  466.       Str(anInt-1:0, aTemp);
  467.       StrCat(StrCat(StrCat(aDst,'Array[0..'), aTemp),'] Of ');
  468.     End Else
  469.       StrCat(StrCat(StrCat(aDst,'?'), aTemp),'?')
  470.   End;
  471.   ExtractWord(aSrc, aSrc, '[]', 1);
  472.   aTemp[0]:= #0;
  473.   For i:= 1 To WordCount(aSrc, ' ') Do
  474.     If Not Modifier(ExtractWord(aWord, aSrc, ' ', i)) Then
  475.       StrCat(StrCat(aTemp, aWord),' ');
  476.  
  477.   Trim(aTemp, aTemp);
  478.   If TheTypeMap^.Search(@aTemp, Index) Then
  479.     With pTypeMap(TheTypeMap^.At(Index))^ Do
  480.       StrCopy(aTemp, T);
  481.   StrCat(aDst, aTemp)
  482. End;
  483.  
  484. Const
  485.   IdMax = 50;
  486. Type
  487.   tIdTable = Array[1..IdMax] Of
  488.     Record
  489.       TheId,
  490.       TheType: Array[0..79] Of Char;
  491.       TheComment: Array[0..300] Of Char
  492.     End;
  493. Var
  494.   IdCnt: Integer;
  495.   IdTable: tIdTable;
  496.  
  497.   Procedure InitId;
  498.   Begin
  499.     IdCnt:= 0
  500.   End;
  501.  
  502.   Procedure AddId (anId, aType, aComment: pChar);
  503.   Begin
  504.     If IdCnt=IdMax Then Begin
  505.       WriteLn('Error: Id Table full. HALT.');
  506.       Halt(1)
  507.     End;
  508.     Inc(IdCnt);
  509.     With IdTable[IdCnt] Do Begin
  510.       Trim(TheId, anId);
  511.       TypeConvert(TheType, aType);
  512.       Trim(TheComment, aComment)
  513.     End
  514.   End;
  515.  
  516.   Function ParseComment(Var Inf: Text; InStr, OutStr: pChar): Boolean;
  517.   Var
  518.     aWord: Array[0..40] Of Char;
  519.   Begin
  520.     ParseComment:= False;
  521.     If StrPos(StrLCopy(aWord, InStr, 5),'/*')=Nil Then Exit;
  522.     While StrPos(InStr, '*/')=Nil Do Begin
  523.       StrCat(OutStr, InStr);
  524.       GetLine(InStr, Inf)
  525.     End;
  526.     StrCat(OutStr, InStr);
  527.     ParseComment:= True
  528.   End;
  529.  
  530.   Function ParseDefine(InStr, OutStr: pChar): Boolean;
  531.   Const
  532.     DefineDelim = ' ';
  533.   Var
  534.     aWord: Array[0..512] Of Char;
  535.     Rest, p: pChar;
  536.     isConst: Boolean;
  537.     i: Integer;
  538.   Begin
  539.     ParseDefine:= False;
  540.     If WordCount(InStr, DefineDelim)<3 Then Exit;
  541.     If  (ExtractWord(aWord, InStr, DefineDelim, 1)<>Nil)
  542.     And (StrIComp(aWord, '#define')=0) Then Begin
  543.       isConst:= False;
  544.       If WhichBlock<>InConst Then
  545.         StrCopy(OutStr,#13#10'Const'#13#10'  ')
  546.       Else
  547.         StrCopy(OutStr,'  ');
  548.       ExtractWord(StrEnd(OutStr), InStr, DefineDelim, 2);
  549.       StrCat(Pad(OutStr, OutStr, 35), '= ');
  550.       Rest:= WordPosition(InStr, DefineDelim, 3);
  551.       StrCopy(aWord, Rest);
  552.       p:= StrPos(aWord,'/*'); If Assigned(p) Then p^:= #0;
  553.       Trim(aWord, aWord);
  554.       If StrLen(aWord)>15 Then Exit;
  555.       p:= StrPos(aWord, '0x');
  556.       While Assigned(p) Do Begin
  557.         isConst:= True;
  558.         p[0]:= ' ';
  559.         p[1]:= '$';
  560.         p:= StrPos(p, '0x')
  561.       End;
  562.       p:= StrScan(aWord, 'L');  {get rid of the f*cking 'L'}
  563.       While Assigned(p) Do Begin
  564.         If (p>aWord) Then Begin
  565.           Dec(p);
  566.           If p^ In ['0'..'9','A'..'F','a'..'f'] Then Begin
  567.             p[1]:= ' ';
  568.             IsConst:= True
  569.           End;
  570.           Inc(p)
  571.         End;
  572.         p:= StrScan(p+1, 'L')
  573.       End;
  574.       If Not IsConst Then
  575.         For i:= 0 To StrLen(aWord)-1 Do
  576.           If aWord[i] In ['0'..'9'] Then Begin
  577.             IsConst:= True;
  578.             Break
  579.           End;
  580.       If Not IsConst Then
  581.         Exit;
  582.       Trim(aWord, aWord);
  583.       StrCat(StrCat(OutStr, aWord), ';');
  584.       p:= StrPos(Rest,'/*');
  585.       If Assigned(p) Then
  586.         StrCat(Pad(OutStr,OutStr, 60), p);
  587.       WhichBlock:= InConst;
  588.       ParseDefine:= True
  589.     End
  590.   End;
  591.  
  592.   Function ParseStruct(Var Inf: Text; InStr, OutStr: pChar): Boolean;
  593.   Var
  594.     aWord,
  595.     aComment,
  596.     RecComment,
  597.     RecName,
  598.     anId, aType,
  599.     Rest: Array[0..300] Of Char;
  600.     possibleArray: Array[0..60] Of Char;
  601.     p, cp: pChar;
  602.     i: Integer;
  603.   Begin
  604.     ParseStruct:= False;
  605.     If  (StrIComp(ExtractWord(aWord, Instr, ' ', 1), 'struct')<>0)
  606.     And (StrIComp(ExtractWord(aWord, Instr, ' ', 2), 'struct')<>0) Then
  607.       Exit;
  608.     p:= Instr;
  609.     Instr:= StrScan(InStr, '{');
  610.     If Not Assigned(InStr) Then Exit;
  611.  
  612.     {-try to parse the structure}
  613.     InStr^:= #0;
  614.     ExtractWord(RecName, p, ' ', WordCount(p,' '));
  615.     Inc(InStr);
  616.     Trim(InStr, InStr);
  617.     If (InStr[0]='/') And (InStr[1]='*') Then
  618.       StrCopy(RecComment, InStr)
  619.     Else
  620.       RecComment[0]:= #0;
  621.     InStr:= StrEnd(InStr);
  622.     cp:= InStr;
  623.     Repeat
  624.       GetLine(cp, Inf);
  625.       p:= StrScan(cp, '}');
  626.       cp:= StrEnd(cp);
  627.       cp^:= ' '; Inc(cp); cp^:= #0
  628.     Until Assigned(p);
  629.     If WordCount(p+1,' ;')>0 Then
  630.       ExtractWord(RecName, p+1, ' ;', 1);
  631.     pChar(p-1)^:= #0;
  632.     InitId;
  633.     p:= InStr;
  634.     Repeat
  635.       cp:= p;
  636.       p:= StrScan(p, ';');
  637.       If Assigned(p) Then Begin
  638.         Trim(aWord, ExtractWord(aWord, cp, ';', 1));
  639.         {extract possible comment}
  640.         cp:= StrPos(aWord, '/*');
  641.         If Assigned(cp) Then Begin
  642.           StrCopy(aComment, cp);
  643.           cp^:= #0
  644.         End Else
  645.           aComment[0]:= #0;
  646.         {-extract id and type}
  647.         cp:= WordPosition(aWord, ' *', WordCount(aWord, ' *')); {last word}
  648.         StrCopy(anId, cp);
  649.         ExtractWord(possibleArray, anId,'[]',2);
  650.         ExtractWord(anId, anId, '[]', 1);
  651.         cp^:= #0;
  652.         StrCopy(aType, aWord);
  653.         If StrLen(possibleArray)>0 Then
  654.           StrCat(StrCat(StrCat(aType,'['),possibleArray),']');
  655.         {-extract comment if after ';'}
  656.         Inc(p);
  657.         While p^=' ' Do Inc(p);
  658.         While (p[0]='/') And (p[1]='*') Do Begin
  659.           {append comment}
  660.           cp:= StrEnd(aComment);
  661.           Repeat
  662.             cp^:= p^;
  663.             Inc(p);
  664.             Inc(cp)
  665.           Until (p[0]=#0) Or ((p[0]='*') And (p[1]='/'));
  666.           cp[0]:= #0; StrCat(Trim(aComment, aComment),' */');
  667.           If p[0]<>#0 Then
  668.             Inc(p,2);
  669.           While p^=' ' Do Inc(p)
  670.         End;
  671.         AddId(anId, aType, aComment)
  672.       End
  673.     Until Not Assigned(p);
  674.  
  675.     {-output the structure}
  676.     If WhichBlock<>InType Then Begin
  677.       StrCopy(OutStr,#13#10'Type'#13#10);
  678.       OutStr:= StrEnd(OutStr)
  679.     End;
  680.     StrCopy(OutStr,'  ');
  681.     StrCat(OutStr, RecName);
  682.     StrCat(OutStr,' = Record');
  683.     If RecComment[0]<>#0 Then
  684.       StrCat(Pad(OutStr, OutStr, 40), RecComment);
  685.     StrCat(OutStr,#13#10);
  686.     For i:= 1 To IdCnt Do Begin
  687.       OutStr:= StrEnd(OutStr);
  688.       With IdTable[i] Do Begin
  689.         StrCopy(OutStr,'    ');
  690.         {If StrIComp(TheId, TheType)=0 Then StrCat(OutStr, '_');} {it works as is}
  691.         StrCat(OutStr, TheId);
  692.         If (i<IdCnt) And (StrIComp(IdTable[i].TheType, IdTable[i+1].TheType)=0) Then
  693.           StrCat(OutStr,', ')
  694.         Else Begin
  695.           StrCat(StrCat(OutStr,': '),TheType);
  696.           If i<IdCnt Then
  697.             StrCat(OutStr,'; ')
  698.         End;
  699.         If TheComment[0]<>#0 Then Begin
  700.           Pad(OutStr, OutStr, 40);
  701.           StrCat(OutStr, TheComment)
  702.         End;
  703.         StrCat(OutStr,#13#10)
  704.       End
  705.     End;
  706.     StrCat(OutStr,'  End;');
  707.     AddStruct(RecName);
  708.     WhichBlock:= InType;
  709.     ParseStruct:= True
  710.   End;
  711.  
  712.   Function IsType (aStr: pChar): Boolean;
  713.   Begin
  714.     IsType:= True;
  715.     If StrPos('unsigned long unsigned int unsigned char far *', aStr)<>Nil Then
  716.       Exit;
  717.     IsType:= False
  718.   End;
  719.  
  720.   Function ParseAPI(Var Inf: Text; InStr, OutStr: pChar): Boolean;
  721.   Var
  722.     FHead,
  723.     aWord,
  724.     Res,
  725.     FuncComment,
  726.     FuncName,
  727.     anId, aType, aComment: Array[0..200] Of Char;
  728.     p, cp, cp2, pStart: pChar;
  729.     i, Indent: Integer;
  730.     IsFunc: Boolean;
  731.     Unknown: Integer;
  732.  
  733.     Function ParseWordAndComment (aComment, aWord, Src: pChar; Delim: Char): pChar;
  734.     {parse Src, search for delim. append comments to aComment, source to aWord}
  735.     Var
  736.       cp: pChar;
  737.     Begin
  738.       Repeat
  739.         While Src^=' ' Do Inc(Src);
  740.         While (Src[0]='/') And (Src[1]='*') Do Begin
  741.           {append comment}
  742.           cp:= StrEnd(aComment);
  743.           Repeat
  744.             cp^:= Src^;
  745.             Inc(Src);
  746.             Inc(cp)
  747.           Until (Src[0]=#0) Or ((Src[0]='*') And (Src[1]='/'));
  748.           cp[0]:= #0; StrCat(Trim(aComment, aComment),' */');
  749.           If Src[0]<>#0 Then
  750.             Inc(Src,2);
  751.           While Src^=' ' Do Inc(Src)
  752.         End;
  753.         cp:= StrEnd(aWord);
  754.         While Not(Src^ In [#0,',','/']) Do Begin
  755.           cp^:= Src^; Inc(Src); Inc(cp)
  756.         End;
  757.         cp^:= #0;
  758.         If Src^=#0 Then Begin
  759.           ParseWordAndComment:= Src;
  760.           Exit
  761.         End
  762.       Until Src^=',';
  763.       Inc(Src);
  764.       While Src^=' ' Do Inc(Src);
  765.       While (Src[0]='/') And (Src[1]='*') Do Begin
  766.         {append comment}
  767.         cp:= StrEnd(aComment);
  768.         Repeat
  769.           cp^:= Src^;
  770.           Inc(Src);
  771.           Inc(cp)
  772.         Until (Src[0]=#0) Or ((Src[0]='*') And (Src[1]='/'));
  773.         cp[0]:= #0; StrCat(Trim(aComment, aComment),' */');
  774.         If Src[0]<>#0 Then
  775.           Inc(Src,2);
  776.         While Src^=' ' Do Inc(Src)
  777.       End;
  778.       ParseWordAndComment:= Src
  779.     End;
  780.  
  781.   Begin
  782.     ParseAPI:= False;
  783.     IsFunc:= False;
  784.     FuncName[0]:= #0;
  785.     Res[0]:= #0;
  786.     If StrPos(InStr,'typedef')<>Nil Then Exit;
  787.     If StrPos(InStr,'#define')<>Nil Then Exit;
  788.     pStart:= StrScan(InStr, '(');
  789.     If Not Assigned(pStart) Then Exit;
  790.     pStart^:= #0;
  791.     {For i:= 1 To WordCount(InStr, ' ') Do
  792.       If Modifier(ExtractWord(aWord, InStr, ' ', i)) Then
  793.         Exit;}
  794.     Trim(FuncName, ExtractWord(FuncName, InStr, ' ', WordCount(InStr, ' ')));
  795.     cp:= WordPosition(InStr, ' ', WordCount(InStr, ' '));
  796.     If Assigned(cp) Then Begin
  797.       cp[0]:= #0;
  798.       Trim(Res, TypeConvert(Res, InStr))
  799.     End Else
  800.       StrCopy(Res, '?????');
  801.     InStr:= pStart+1;
  802.     cp:= InStr;
  803.     p:= StrScan(cp, ';');
  804.     While Not Assigned(p) Do Begin
  805.       cp:= StrEnd(cp);
  806.       cp^:= ' '; Inc(cp);
  807.       GetLine(cp, Inf);
  808.       p:= StrScan(cp, ';')
  809.     End;
  810.     StrCopy(FuncComment, p+1);
  811.     Repeat
  812.       Dec(p)
  813.     Until (p<=InStr) Or (p^=')');
  814.     p^:= #0;
  815.  
  816.     InitId;
  817.     Unknown:= 0;
  818.     p:= InStr;
  819.     While p^<>#0 Do Begin
  820.       aComment[0]:= #0;
  821.       aWord[0]:= #0;
  822.       p:= ParseWordAndComment(aComment, aWord, p, ',');
  823.       Trim(aWord, aWord);
  824.       TypeConvert(aType, aWord);
  825.       If (StrIComp(aType, aWord)<>0) Or (WordCount(aWord,' ')=1) Then Begin
  826.       {non-Ansi declaration}
  827.         Inc(Unknown);
  828.         Str(Unknown, anId);
  829.         Move(anId[0], anId[3], StrLen(anId)+1);
  830.         anId[0]:= 'P'; anId[1]:= 'a'; anId[2]:= 'r';
  831.       End Else Begin
  832.         cp:= WordPosition(aWord, ' *', WordCount(aWord, ' *')); {last word}
  833.         If Assigned(cp) Then Begin
  834.           StrCopy(anId, cp);
  835.           cp^:= #0
  836.         End;
  837.         StrCopy(aType, aWord)
  838.       End;
  839.       AddId(anId, aType, aComment)
  840.     End;
  841.  
  842.     StrCopy(OutStr, '  Function ');
  843.     StrCat(OutStr, FuncName);
  844.     StrCat(OutStr, ' (');
  845.     Indent:= StrLen(OutStr);
  846.     OutStr:= StrEnd(OutStr);
  847.     aWord[0]:= #0;
  848.     For i:= 1 To IdCnt Do
  849.       With IdTable[i] Do Begin
  850.         StrCat(aWord, TheId);
  851.         If (i<IdCnt) And (StrIComp(IdTable[i].TheType, IdTable[i+1].TheType)=0) Then
  852.           StrCat(aWord, ', ')
  853.         Else Begin
  854.           StrCat(StrCat(aWord, ': '), TheType);
  855.           If i<IdCnt Then StrCat(aWord, '; ')
  856.         End;
  857.         Trim(aWord, aWord);
  858.         If TheComment[0]<>#0 Then
  859.           StrCat(Pad(aWord, aWord, 60-Indent), TheComment);
  860.         If (Indent+StrLen(aWord)>90) Or (TheComment[0]<>#0) Then Begin
  861.           StrCopy(OutStr, aWord); OutStr:= StrEnd(OutStr);
  862.           If i<IdCnt Then Begin
  863.             StrCat(OutStr, #13#10);
  864.             Pad(OutStr, OutStr, 2+Indent)
  865.           End;
  866.           OutStr:= StrEnd(OutStr);
  867.           aWord[0]:= #0
  868.         End
  869.       End;
  870.     StrCat(StrCat(StrCat(StrCat(StrCat(OutStr, aWord),'): '), Res),';'), FuncComment);
  871.     AddFunc(FuncName);
  872.     WhichBlock:= InFunc;
  873.     ParseAPI:= True
  874.   End;
  875.  
  876.   Procedure GenerateReport (Var Out: Text);
  877.     Procedure RepFunc (Item: Pointer); Far;
  878.     Var
  879.       aDLL, anOrd: Array[0..60] Of Char;
  880.       aLine: Array[0..200] Of Char;
  881.     Begin
  882.       StrCopy(aDLL,'?');
  883.       StrCopy(anOrd, '?');
  884.       If HasImports Then
  885.         GetOrdDLL(Item, aDLL, anOrd);
  886.       StrCat(StrCat(StrCopy(aLine,'  Function '), pChar(Item)),';');
  887.       StrCat(Pad(aLine, aLine, 42),'External ''');
  888.       StrCat(StrCat(aLine, aDLL), '''');
  889.       StrCat(Pad(aLine, aLine, 62),'Index ');
  890.       StrCat(StrCat(Pad(aLine, aLine, 72-StrLen(anOrd)), anOrd),';');
  891.       WriteLn(Out,aLine)
  892.     End;
  893.     Procedure VeriPascal (Item: Pointer); Far;
  894.     Var
  895.       aLine: Array[0..200] Of Char;
  896.       aName: Array[0..60] Of Char;
  897.     Begin
  898.       Pad(aName, Item, 35);
  899.       StrCat(StrCopy(aLine,'  veri('''), aName);
  900.       StrCat(StrCat(StrCat(aLine,''',sizeof('),aName),'));');
  901.       WriteLn(Out,aLine)
  902.     End;
  903.     Procedure VeriC (Item: Pointer); Far;
  904.     Var
  905.       aLine: Array[0..200] Of Char;
  906.       aName: Array[0..60] Of Char;
  907.     Begin
  908.       Pad(aName, Item, 35);
  909.       StrCat(StrCopy(aLine,'  veri("'), aName);
  910.       StrCat(StrCat(StrCat(aLine,'",sizeof('),aName),'));');
  911.       WriteLn(Out,aLine)
  912.     End;
  913.   Begin
  914.     WriteLn(Out, 'Implementation');
  915.     TheFuncs^.ForEach(@RepFunc);
  916.     WriteLn(Out, 'End.');
  917.     WriteLn(Out);
  918.     WriteLn(Out, '--- snip --- snip --- snip ---');
  919.     WriteLn(Out,#13#10#13#10'{Pascal verification program for '+Dstname+' }');
  920.     WriteLn(Out,'Program VeriP;'#13#10+
  921.                 'Uses'#13#10+
  922.                 '  '+DstName+';'#13#10);
  923.     WriteLn(Out,'Procedure Veri (aStr: pChar; aSize: Integer);');
  924.     WriteLn(Out,'Begin');
  925.     WriteLn(Out,'  WriteLn(''Size of '',aStr,''= '',aSize:5);');
  926.     WriteLn(Out,'End;'#13#10);
  927.     WriteLn(Out,'Begin');
  928.     WriteLn(Out,'  WriteLn(''verification of '+DstName+' for Pascal:'');');
  929.     TheStructs^.ForEach(@VeriPascal);
  930.     WriteLn(Out,'End.');
  931.     WriteLn(Out);
  932.     WriteLn(Out,#13#10#13#10'/* C verification program for '+DstName+' */');
  933.     WriteLn(Out,'#include <stdio.h>'#13#10+
  934.                 '#include "'+DstName+'.h"'#13#10+
  935.                 'void veri (char *aStr, int aSize)'#13#10+
  936.                 '{ printf("Size of %s= %5i\n",aStr,aSize); }'#13#10);
  937.     WriteLn(Out,'void main (void)'#13#10+
  938.                 '{ printf("verification of '+DstName+' for C:\n");');
  939.     TheStructs^.ForEach(@VeriC);
  940.     WriteLn(Out,'}');
  941.   End;
  942.  
  943. Const
  944.   LineBufSize = 5000;
  945.   IoBufSize   = 32*1024;
  946. Type
  947.   IoBuf = Array[0..IoBufSize-1] Of Char;
  948.   pIoBuf = ^IoBuf;
  949. Var
  950.   Inf, Out: Text;
  951.   InStr,
  952.   OutStr: pChar;
  953. Begin
  954.   WriteLn(Version,', written 1993 by P. Sawatzki');
  955.   If Not (ParamCount In [2,3]) Then Begin
  956.     WriteLn('Usage: H2Pas InFile OutFile [ImportList]');
  957.     Halt
  958.   End;
  959.   CreateCollections;
  960.   ReadIni;
  961.   If ParamStr(3)<>'' Then
  962.     Imports:= ParamStr(3)
  963.   Else
  964.     Imports:= JustName(ParamStr(1))+'.Imp';
  965.   {$i-}
  966.   Assign(Inf, ParamStr(1)); Reset(Inf);
  967.   If IoResult<>0 Then Fatal('Input file not found');
  968.   Assign(Out, ParamStr(2)); ReWrite(Out);
  969.   If IoResult<>0 Then Fatal('Unable to create output file');
  970.   DstName:= JustName(ParamStr(2));
  971.   GetMem(InStr,  LineBufSize);
  972.   GetMem(OutStr, LineBufSize);
  973.   Write('Processing files...');
  974.   HeaderInfo(Out);
  975.   While Not Eof(Inf) Do Begin
  976.     GetLine(InStr, Inf);
  977.     OutStr[0]:= #0;
  978.     If ParseComment(Inf, InStr, OutStr)
  979.     Or ParseDefine(InStr, OutStr)
  980.     Or ParseStruct(Inf, InStr, OutStr)
  981.     Or ParseAPI(Inf, InStr, OutStr) Then
  982.       OutLn(Out, OutStr)
  983.     Else
  984.       OutLn(Out, InStr)
  985.   End;
  986.   WriteLn('Done.');
  987.   Write('Reading import file ',Imports,'...');
  988.   ReadImports(Imports);
  989.   If HasImports Then
  990.     WriteLn('Done.')
  991.   Else
  992.     WriteLn('Not found.'#13#10+
  993.             '(generate an import file using "EXEHDR File.DLL >'+JustName(ParamStr(1))+
  994.             '.Imp")');
  995.   Write('Appending report...');
  996.   GenerateReport(Out);
  997.   WriteLn('Done.');
  998.   DestroyCollections;
  999.   FreeMem(InStr,  LineBufSize);
  1000.   FreeMem(OutStr, LineBufSize);
  1001.   Close(Inf);
  1002.   Close(Out)
  1003. End.
  1004.